/****************************************************************************
** @brief
****************************************************************************/

#include <QSqlQuery>
#include <QSqlRecord>

#include "baseRecord.h"

#include <QDebug>
//#define BASERECORD_DEBUG

BaseRecord::BaseRecord(QObject *parent) : QObject(parent)
{

}

BaseRecord::~BaseRecord()
{
    sql_db_.close();
}

void BaseRecord::InitRecorDB(QString db_name)
{
    db_name_ = db_name;

    ConnectDB();
    OpenDB();
}

void BaseRecord::CreateRecordTable(QString table_name, QString table_field)
{
    table_name_ = table_name;

    CreateTable(table_field);
}

void BaseRecord::InsertRecord(QVariantHash vhash)
{
    mutex_.lock();

    QSqlQuery sqlQuery;
    QString queryStr, fieldStr, valueStr;
    QHashIterator<QString, QVariant> ki(vhash), ti(vhash); // 针对 Key 和 T 的 迭代器

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return;
    }

    if (vhash.isEmpty()) {
        mutex_.unlock();
        return;
    }

    queryStr = "INSERT INTO " + table_name_ + " ";
    fieldStr = "(";
    valueStr = "VALUES (";
    while (ki.hasNext()) {
        ki.next();
        fieldStr += ki.key();
        valueStr += "?";
        if (ki.hasNext()) {
            fieldStr += ", ";
            valueStr += ", ";
        }
    }
    fieldStr += ") ";
    valueStr += ")";
    queryStr += fieldStr + valueStr;

#ifdef BASERECORD_DEBUG
    qDebug() << "[BASERECORD]-> insert:" << queryStr;
#endif

    sqlQuery.prepare(queryStr);

    while (ti.hasNext()) {
        ti.next();
        sqlQuery.addBindValue(ti.value());
    }

    if (!sqlQuery.exec()) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> insert failed";
#endif
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> insert success";
#endif
    }

    mutex_.unlock();
}

void BaseRecord::DeleteRecord(QString targetKey, QVariant targetValue)
{
    mutex_.lock();

    QSqlQuery sqlQuery;
    QString queryStr;

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return;
    }

    if (targetKey.isEmpty() || targetValue.isNull()) {
        mutex_.unlock();
        return;
    }

    queryStr = "DELETE FROM " + table_name_ + " WHERE " + targetKey + " = '" + targetValue.toString() + "'";

    sqlQuery.prepare(queryStr);

    if (!sqlQuery.exec()) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> delete failed";
#endif
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> delete success";
#endif
    }

    mutex_.unlock();
}

void BaseRecord::UpdateRecord(QVariantHash vhash, QString targetKey, QVariant targetValue)
{
    mutex_.lock();

    QSqlQuery sqlQuery;
    QString queryStr, setStr, whereStr;
    QHashIterator<QString, QVariant> i(vhash);

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return;
    }

    if (vhash.isEmpty()) {
        mutex_.unlock();
        return;
    }
    if (targetKey.isEmpty() || targetValue.isNull()) {
        mutex_.unlock();
        return;
    }

    queryStr = "UPDATE " + table_name_ + " SET ";
    while (i.hasNext()) {
        i.next();
        setStr += i.key() + " = '" + i.value().toString() + "'";
        if (i.hasNext()) {
            setStr += ", ";
        } else {
            setStr += " ";
        }
    }
    whereStr = "WHERE " + targetKey + " = '" + targetValue.toString() + "'";
    queryStr += setStr + whereStr;

#ifdef BASERECORD_DEBUG
    qDebug() << "[BASERECORD]-> update:" << queryStr;
#endif

    sqlQuery.prepare(queryStr);

    if (!sqlQuery.exec()) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> update failed.";
#endif
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> update success.";
#endif
    }

    mutex_.unlock();
}

void BaseRecord::UpdateRecord(QString exitsKey, QVariant exitsValue, QString targetKey, QVariant targetValue)
{
    mutex_.lock();

    QSqlQuery sqlQuery;
    QString queryStr, setStr, whereStr;

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return;
    }

    if (exitsKey.isEmpty() || exitsValue.isNull() || targetKey.isEmpty() || targetValue.isNull()) {
        mutex_.unlock();
        return;
    }

    queryStr = "UPDATE " + table_name_ + " SET ";
    setStr = exitsKey + " = '" + exitsValue.toString() + "' ";
    whereStr = "WHERE " + targetKey + " = '" + targetValue.toString() + "'";
    queryStr += setStr + whereStr;

#ifdef BASERECORD_DEBUG
    qDebug() << "[BASERECORD]-> update:" << queryStr;
#endif

    sqlQuery.prepare(queryStr);

    if (!sqlQuery.exec()) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> update failed..";
#endif
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> update success..";
#endif
    }

    mutex_.unlock();
}

bool BaseRecord::IsRecordExist(QString targetKey, QVariant targetValue)
{
    mutex_.lock();

    bool result;
    QSqlQuery sqlQuery;
    QString queryStr;

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return false;
    }

    if (targetKey.isEmpty() || targetValue.isNull()) {
        mutex_.unlock();
        return false;
    }

    queryStr = "SELECT * FROM " + table_name_ + " WHERE " + targetKey + " = '" + targetValue.toString() + "'";

    sqlQuery.prepare(queryStr);

    result = sqlQuery.exec();
    if (!result) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> select failed...";
#endif
        mutex_.unlock();
        return result;
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> select success...";
#endif
    }

    if (!sqlQuery.next()) {
        result = false;
    }

    mutex_.unlock();

    return result;
}

QVariantHash BaseRecord::RecordExistData(QString targetKey, QVariant targetValue)
{
    mutex_.lock();

    bool result;
    QSqlQuery sqlQuery;
    QString queryStr;
    QVariantHash vhash;
    QSqlRecord sqlRecord;

    if (!sql_db_.isOpen()) {
        mutex_.unlock();
        return vhash;
    }

    if (targetKey.isEmpty() || targetValue.isNull()) {
        mutex_.unlock();
        return vhash;
    }

    queryStr = "SELECT * FROM " + table_name_ + " WHERE " + targetKey + " = '" + targetValue.toString() + "'";

    sqlQuery.prepare(queryStr);

    result = sqlQuery.exec();
    if (!result) {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> select failed....";
#endif
    } else {
#ifdef BASERECORD_DEBUG
        qDebug() << "[BASERECORD]-> select success....";
#endif
    }

    if (result) {
        if (sqlQuery.next()) {
            sqlRecord = sqlQuery.record();
            for (int i = 0; i < sqlRecord.count(); ++i) {
                vhash[sqlRecord.fieldName(i)] = sqlQuery.value(i);
#ifdef BASERECORD_DEBUG
                //qDebug() << "[BASERECORD]-> field:" << sqlRecord.fieldName(i) << "value:" << sqlQuery.value(i).toString();
#endif
            }
        }
    }

    mutex_.unlock();

    return vhash;
}

bool BaseRecord::IsDBOpen()
{
    return sql_db_.isOpen();
}

void BaseRecord::ConnectDB()
{
    if (QSqlDatabase::contains("qt_sql_default_connection")) {
        sql_db_ = QSqlDatabase::database("qt_sql_default_connection");
    } else {
        sql_db_ = QSqlDatabase::addDatabase("QSQLITE"); //SQLite version 3
        sql_db_.setDatabaseName("./" + db_name_);
    }
}

void BaseRecord::OpenDB()
{
    if (!sql_db_.open()) {
        qDebug() << "[BASERECORD]-> db open failed";
    } else {
        qDebug() << "[BASERECORD]-> db open success";
    }
}

void BaseRecord::CloseDB()
{
    sql_db_.close();
}

void BaseRecord::CreateTable(QString field)
{
    if (!sql_db_.isOpen()) {
        qDebug() << "[BASERECORD]-> table create failed, reason is db open failed";
        return;
    }

    if (field.isEmpty()) {
        return;
    }

    /*
     * idx - 主键/自动增长/非空
     */

    QSqlQuery sqlQuery;
    QString creatTableString = "CREATE TABLE IF NOT EXISTS " + table_name_ + " ("
                               "idx INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
                               + field + ");";

    sqlQuery.prepare(creatTableString);
    if (!sqlQuery.exec()) {
        qDebug() << "[BASERECORD]-> table create failed";
    } else {
        qDebug() << "[BASERECORD]-> table create success";
    }
}
